home *** CD-ROM | disk | FTP | other *** search
- {****************************************************}
- { CFWDesktop.p}
- {}
- { The FWDesktop Class}
- {}
- { A Desktop which support floating windows. Floating windows are}
- { always active and remain above all "regular" windows.}
- {}
- { SUPERCLASS = CDesktop}
- {}
- { Copyright ⌐ 1989, Symantec Corporation. All rights reserved. }
- {}
- {****************************************************}
-
- unit CFWDesktop;
-
- interface
-
- uses
- SysEqu, TCL, MoreTCL;
-
-
- implementation
-
-
- {** Class Constant **}
-
- const
- NO_DRAG = $80008000; { Flag signalling an aborted drag }
-
-
- {****************************************************}
- { IFWDesktop}
- {}
- { Initialize a FWDesktop object}
- {}
- {****************************************************}
-
- procedure CFWDesktop.IFWDesktop (aSupervisor: CBureaucrat);
- var
- theFloats: CList; { Altered by TCL Weaver 1.0 (5/9/90) }
-
- begin
- IDesktop(aSupervisor); { Initialize superclass }
-
- new(theFloats); { Initialize our list of floating windows }
- itsFloats := theFloats; { Altered by TCL Weaver 1.0 (5/9/90) }
- itsFloats.IList;
- topFloat := nil;
- end;
-
-
- {****************************************************}
- { Free (OVERRIDE)}
- {}
- { Dispose of a FWDesktop}
- {}
- {****************************************************}
-
- procedure CFWDesktop.Free;
- begin
- itsFloats.DisposeAll; { Get rid of floating }
- itsWindows.DisposeAll; { and regular windows }
-
- ClosePort(macPort); { Throw out QuickDraw port and all }
- DisposPtr(Ptr(macPort)); { assocated data structures }
-
- inherited Free; { Pass message on to superclass }
- end;
-
-
- {****************************************************}
- { AdjustCursor (OVERRIDE)}
- {}
- { Mouse is located where no other object wants to set the cursor shape.}
- { Adjust the shape to the standard arrow cursor}
- {}
- {****************************************************}
-
- type
- RgnHandlePtr = ^RgnHandle;
-
- procedure Window_DiffContRgn (theWindow: CWindow; mouseRgn: Ptr);
-
- {Subtract content region of floating window from mouseRgn}
-
- begin
- if theWindow.IsVisible then
- DiffRgn(RgnHandlePtr(mouseRgn)^, WindowPeek(theWindow.GetMacPort)^.contRgn, RgnHandlePtr(mouseRgn)^);
- end;
-
-
- procedure CFWDesktop.AdjustCursor (where: Point; mouseRgn: RgnHandle);
- begin
- inherited AdjustCursor(where, mouseRgn);
-
- if topFloat <> nil then
- itsFloats.DoForEach1(Window_DiffContRgn, @mouseRgn);
- end;
-
-
- {****************************************************}
- { AddWind (OVERRIDE)}
- {}
- { Add a window to the desktop}
- {}
- {****************************************************}
-
- procedure CFWDesktop.AddWind (theWindow: CWindow);
- begin
- if theWindow.IsFloating then
- itsFloats.Prepend(theWindow)
- else
- itsWindows.Add(theWindow);
- end;
-
-
- {****************************************************}
- { RemoveWind (OVERRIDE)}
- {}
- { Remove a window from the desktop}
- {}
- {****************************************************}
-
- procedure CFWDesktop.RemoveWind (theWindow: CWindow);
- begin
- if theWindow.IsVisible then
- HideWind(theWindow); { Hide window before discarding it }
-
- if theWindow.IsFloating then
- itsFloats.Remove(theWindow)
- else
- itsWindows.Remove(theWindow);
- end;
-
-
- {****************************************************}
- { SelectWind (OVERRIDE)}
- {}
- { Select a window by bringing it to the front and making it active}
- {}
- {****************************************************}
-
- procedure CFWDesktop.SelectWind (theWindow: CWindow);
- var
- aDAIsActive: Boolean; { TRUE if a DA is the front window }
- aWindow: CWindow; { Window object }
- oldTop: CWindow; { Former top regular window }
- macWPtr: WindowPtr; { Ptr to Toolbox window record }
- theDA: WindowPtr; { Ptr to window record for a DA }
-
- begin
- { Check if a DA is running }
-
- aDAIsActive := IsSystemWindow(WindowPeek(FrontWindow));
-
- { Do nothing if the window is at }
- { the top of its layer and a DA }
- { is not active }
-
- if ((theWindow = topWindow) or (theWindow = topFloat)) and not aDAIsActive then
- Exit(SelectWind)
- else
- begin
- if aDAIsActive then
-
- begin { A DA is currently running. Need }
- { to activate our application. }
-
- { Find our bottom-most window }
-
- aWindow := GetBottomWindow;
- if aWindow = nil then
- macWPtr := nil
- else
- macWPtr := aWindow.macPort;
-
- { Put all DAs behind our bottom }
- { window, maintaining the }
- { ordering of the DAs }
-
- theDA := FrontWindow;
- while (IsSystemWindow(WindowPeek(theDA))) do
- begin
- SendBehind(theDA, macWPtr);
- macWPtr := theDA;
- theDA := FrontWindow;
- end;
- end;
-
- if theWindow.IsFloating then
- begin { Select a floating window }
-
- if theWindow <> topFloat then
-
- begin { If this isn't the top float ... }
- { Make it the front window }
-
- BringToFront(theWindow.macPort);
-
- { Update our window list }
-
- itsFloats.BringFront(theWindow);
-
- theWindow.Show; { Make it visible, if necessary }
- topFloat := theWindow; { Mark it as the top float }
- end;
-
- end
- else if theWindow <> topWindow then
- begin
- { If this isn't the top regular... }
- oldTop := topWindow; { Save the current top regular }
-
- aWindow := CWindow(itsFloats.LastItem);
- if aWindow = nil then
- { Put it in front if there are }
- { no floating windows }
-
- BringToFront(theWindow.macPort)
- else
- { Otherwise, put it behind the }
- { bottom floating window }
-
- BringBehind(theWindow.macPort, aWindow.macPort);
-
- { Update our window list }
-
- itsWindows.BringFront(theWindow);
-
- theWindow.ShowOrHide(TRUE); { Make it visible, if necessary }
-
- topWindow := theWindow; { Mark it as the top regular }
-
- if aDAIsActive then
- begin
- if oldTop <> nil then
- begin
- HiliteWindow(oldTop.macPort, FALSE);
- CDirector(oldTop.itsSupervisor).active := FALSE;
- end;
- CDirector(topWindow.itsSupervisor).active := TRUE;
-
- end
- else
- begin
-
- if oldTop <> nil then { Deactivate the former top }
- { regular window }
- oldTop.Deactivate;
-
- topWindow.Activate; { Activate the new top window }
- end;
- end;
-
- LongPtr(CurActivate)^ := longint(nil); { Nuke any pending activate event }
- end;
- end;
-
-
- {****************************************************}
- { ShowWind (OVERRIDE)}
- {}
- { Make a window visible on the desktop}
- {}
- {****************************************************}
-
- procedure CFWDesktop.ShowWind (theWindow: CWindow);
- begin
- if theWindow.IsFloating then
- begin
- ShowHide(theWindow.macPort, TRUE);
- theWindow.Activate;
- CalcTopFloat;
- end
- else
- inherited ShowWind(theWindow);
- end;
-
-
- {****************************************************}
- { HideWind (OVERRIDE)}
- {}
- { Make a window invisible on the desktop}
- {}
- {****************************************************}
-
- procedure CFWDesktop.HideWind (theWindow: CWindow);
- begin
- if theWindow.IsFloating then
- begin
- ShowHide(theWindow.macPort, FALSE);
- if theWindow = topFloat then
- CalcTopFloat;
- end
- else
- inherited HideWind(theWindow);
- end;
-
-
- {****************************************************}
- { DragWind (OVERRIDE)}
- {}
- { Drag a window on the desktop}
- {}
- {****************************************************}
-
- procedure CFWDesktop.DragWind (theWindow: CWindow; macEvent: EventRecord);
- var
- savePort: GrafPtr; { The current QD port }
- macWindow: WindowPtr; { Toolbox window pointer }
- corner: Point; { Top left corner of window }
- dragBox: Rect; { Where window may be dragged }
- newLoc: longint; { New location after drag }
- hDrag: integer; { Distance dragged horizontally }
- vDrag: integer; { Distance dragged vertically }
-
- begin
- if (theWindow <> topWindow) and (theWindow <> topFloat) and (BAND(macEvent.modifiers, cmdKey) = 0) then
-
- { Drag for an underlying window }
- { without the command key being }
- { pressed. Select window before }
- { performing the drag. }
- SelectWind(theWindow);
-
- if not StillDown then { Take a quick exit if the mouse }
- Exit(DragWind); { has already been released }
-
- GetPort(savePort); { Save the current port }
-
- { Find Global coords of the top }
- { left corner of the window }
-
- macWindow := WindowPtr(theWindow.GetMacPort);
- SetPort(macWindow);
- corner := topLeft(macWindow^.portRect);
- LocalToGlobal(corner);
-
- SetPort(macPort); { Use desktop's port }
- PenNormal; { Use standard pen characteristics }
-
- dragBox := bounds; { Don't allow drag too close to }
- { the edge of the screen }
-
- InsetRect(dragBox, DRAG_MARGIN, DRAG_MARGIN);
-
- { Drag dotted outline of window }
-
- CopyRgn(WindowPeek(macWindow)^.strucRgn, gUtilRgn);
- newLoc := DragGrayRgn(gUtilRgn, macEvent.where, dragBox, dragBox, 0, nil);
- hDrag := LoWord(newLoc);
- vDrag := HiWord(newLoc);
-
- { If a drag actually occurred, put }
- { window at new location }
-
- if (newLoc <> NO_DRAG) and ((hDrag <> 0) or (vDrag <> 0)) then
- MoveWindow(macWindow, LoWord(newLoc) + corner.h, HiWord(newLoc) + corner.v, FALSE);
-
- SetPort(savePort); { Restore the original port }
- end;
-
-
- {****************************************************}
- { Show (OVERRIDE)}
- {}
- { Make a Desktop visible by showing all its windows}
- {}
- {****************************************************}
-
- procedure CFWDesktop.Show;
- begin
- if not visible then
- begin { Do nothing if already visible }
- visible := TRUE;
- itsFloats.DoForEach(Window_Show);
- itsWindows.DoForEach(Window_Show);
- end;
- end;
-
-
- {****************************************************}
- { Hide (OVERRIDE)}
- {}
- { Make a Desktop invisible by hiding all its windows}
- {}
- {****************************************************}
-
- procedure CFWDesktop.Hide;
- begin
- if visible then
- begin { Do nothing if already invisible }
- visible := FALSE;
- itsWindows.DoForEach(Window_Hide);
- itsFloats.DoForEach(Window_Hide);
- end;
- end;
-
-
- {****************************************************}
- { Activate (OVERRIDE)}
- {}
- { Activate a desktop by activating all floating windows and the}
- { top regular window}
- {}
- {****************************************************}
-
- procedure CFWDesktop.Activate;
- begin
- if not active then
- begin { Do nothing if already active }
- active := TRUE;
- itsFloats.DoForEach(Window_Activate);
- if topWindow <> nil then
- topWindow.Activate;
- end;
- end;
-
-
- {****************************************************}
- { Deactivate (OVERRIDE)}
- {}
- { Deactivate a desktop by deactivating all floating windows and the}
- { top regular window}
- {}
- {****************************************************}
-
- procedure CFWDesktop.Deactivate;
- begin
- if active then
- begin { Do nothing if already inactive }
- active := FALSE;
- itsFloats.DoForEach(Window_Deactivate);
- if topWindow <> nil then
- topWindow.Deactivate;
- end;
- end;
-
-
- {****************************************************}
- { GetBottomWindow (OVERRIDE)}
- {}
- { Return the Desktop's bottom-most window (not including DAs).}
- {}
- {****************************************************}
-
- function CFWDesktop.GetBottomWindow: CWindow;
- var
- bottomWindow: CWindow;
-
- begin
- bottomWindow := inherited GetBottomWindow;
-
- if bottomWindow = nil then
- GetBottomWindow := CWindow(itsFloats.LastItem)
- else
- GetBottomWindow := bottomWindow;
- end;
-
-
- {****************************************************}
- { CalcTopFloat}
- {}
- { Set topFloat to the first visible window in itsFloats (if any). }
- {}
- {****************************************************}
-
- procedure CFWDesktop.CalcTopFloat;
- begin
- topFloat := CWindow(itsFloats.FirstSuccess(Window_IsVisible));
- end;
-
-
- {****************************************************}
- { Cleanup (OVERRIDE)}
- {}
- { Move THINK Pascal's windows behind our application's windows. }
- {}
- { If we are running in the THINK Pascal environment, one or more }
- { of THINK Pascal's windows may (from our viewpoint) "suddenly" }
- { appear directly behind our top floating window. This happens if }
- { the user clicks on a Pascal window, or if the user breaks into the }
- { source-level debugger, opens up some windows, and resumes }
- { execution. In these situations, THINK Pascal takes care of bringing }
- { our frontmost (floating) window back to the top }
- { (when CApplication.Run calls FrontWindow), but we are }
- { responsible for bringing the rest of our floating windows and our }
- { top non-floating window forward. If we are NOT running in the }
- { THINK Pascal environment, this code will have no ill effects. }
- {}
- {****************************************************}
-
- procedure CFWDesktop.Cleanup;
-
- var
- testWindow, bottomFloat, lastWindowMoved: WindowPeek;
-
- begin
-
- { No cleanup necessary if there are no floating windows. }
-
- if itsFloats.FirstItem <> nil then { We use itsFloats.FirstItem instead }
- { of topFloat because if topFloat = nil, }
- { that means there are no VISIBLE }
- { floating windows; there still may be }
- { an invisible floating window, which }
- { THINK Pascal would consider our }
- { application's frontmost window. }
-
- begin
- lastWindowMoved := nil; { We will use this var to preserve the ordering }
- { of the Pascal windows. }
-
- if topWindow <> nil then
-
- { If there are THINK Pascal windows behind the top floating window, }
- { then send the Pascal windows behind the top non-floating window }
- { (topWindow). }
-
- repeat
- testWindow := WindowPeek(CWindow(itsFloats.FirstItem).GetMacPort)^.nextWindow;
- if testWindow^.windowKind >= pascalKind then
- begin
- if lastWindowMoved = nil then
- SendBehind(WindowPtr(testWindow), topWindow.macPort)
- else
- SendBehind(WindowPtr(testWindow), WindowPtr(lastWindowMoved));
- lastWindowMoved := testWindow;
- end;
- until testWindow^.windowKind < pascalKind
-
- else
-
- { There are no visible non-floating windows. If there are THINK Pascal windows }
- { behind the top floating window, then send the }
- { Pascal windows behind the bottom floating window. }
-
- begin
- bottomFloat := WindowPeek(CWindow(itsFloats.LastItem).GetMacPort);
- if itsFloats.FirstItem <> itsFloats.LastItem then
- repeat
- testWindow := WindowPeek(CWindow(itsFloats.FirstItem).GetMacPort)^.nextWindow;
- if testWindow^.windowKind >= pascalKind then
- begin
- if lastWindowMoved = nil then
- SendBehind(WindowPtr(testWindow), WindowPtr(bottomFloat))
- else
- SendBehind(WindowPtr(testWindow), WindowPtr(lastWindowMoved));
- lastWindowMoved := testWindow;
- end;
- until testWindow^.windowKind < pascalKind;
- end;
- end;
- end;
-
-
- end.